home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / dir / scandir.c < prev    next >
C/C++ Source or Header  |  1988-09-28  |  2KB  |  92 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #if defined(LIBC_SCCS) && !defined(lint)
  8. static char sccsid[] = "@(#)scandir.c    5.2 (Berkeley) 3/9/86";
  9. #endif LIBC_SCCS and not lint
  10.  
  11. /*
  12.  * Scan the directory dirname calling select to make a list of selected
  13.  * directory entries then sort using qsort and compare routine dcomp.
  14.  * Returns the number of entries and a pointer to a list of pointers to
  15.  * struct direct (through namelist). Returns -1 if there were any errors.
  16.  */
  17.  
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <sys/dir.h>
  21.  
  22. scandir(dirname, namelist, select, dcomp)
  23.     char *dirname;
  24.     struct direct ***namelist;
  25.     int (*select)(), (*dcomp)();
  26. {
  27.     register struct direct *d, *p, **names;
  28.     register int nitems;
  29.     register char *cp1, *cp2;
  30.     struct stat stb;
  31.     long arraysz;
  32.     DIR *dirp;
  33.  
  34.     if ((dirp = opendir(dirname)) == NULL)
  35.         return(-1);
  36.     if (fstat(dirp->dd_fd, &stb) < 0)
  37.         return(-1);
  38.  
  39.     /*
  40.      * estimate the array size by taking the size of the directory file
  41.      * and dividing it by a multiple of the minimum size entry. 
  42.      */
  43.     arraysz = (stb.st_size / 24);
  44.     names = (struct direct **)malloc(arraysz * sizeof(struct direct *));
  45.     if (names == NULL)
  46.         return(-1);
  47.  
  48.     nitems = 0;
  49.     while ((d = readdir(dirp)) != NULL) {
  50.         if (select != NULL && !(*select)(d))
  51.             continue;    /* just selected names */
  52.         /*
  53.          * Make a minimum size copy of the data
  54.          */
  55.         p = (struct direct *)malloc(DIRSIZ(d));
  56.         if (p == NULL)
  57.             return(-1);
  58.         p->d_ino = d->d_ino;
  59.         p->d_reclen = d->d_reclen;
  60.         p->d_namlen = d->d_namlen;
  61.         for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; );
  62.         /*
  63.          * Check to make sure the array has space left and
  64.          * realloc the maximum size.
  65.          */
  66.         if (++nitems >= arraysz) {
  67.             if (fstat(dirp->dd_fd, &stb) < 0)
  68.                 return(-1);    /* just might have grown */
  69.             arraysz = stb.st_size / 12;
  70.             names = (struct direct **)realloc((char *)names,
  71.                 arraysz * sizeof(struct direct *));
  72.             if (names == NULL)
  73.                 return(-1);
  74.         }
  75.         names[nitems-1] = p;
  76.     }
  77.     closedir(dirp);
  78.     if (nitems && dcomp != NULL)
  79.         qsort(names, nitems, sizeof(struct direct *), dcomp);
  80.     *namelist = names;
  81.     return(nitems);
  82. }
  83.  
  84. /*
  85.  * Alphabetic order comparison routine for those who want it.
  86.  */
  87. alphasort(d1, d2)
  88.     struct direct **d1, **d2;
  89. {
  90.     return(strcmp((*d1)->d_name, (*d2)->d_name));
  91. }
  92.